function [varargout] = gzip(varargin)
% gzip  - console/shell interface for MATLAB
%
% a simple interface to gzip functionality that *should* work under
% MS-Windows as well (Windows binary courtesy of www.gzip.org).
%
% since all arguments must be strings, you can use both command and
% functional calling convention in MATLAB. as a function, you can get
% both return status and console output, only return status, or nothing.
%
% gzip('arg1','arg2',...);
% status = gzip('arguments');
% [status,output] = gzip('arg1','arg2',...);
%
% all arguments are glued together with a blank, so it doesn't matter
% whether you call with one argument or several.
%
% examples:
%
% gzip -9 /tmp/hallo.bmp
% s=gzip('-d /home/user123/myfiles/vol1.img.gz');
% gzip -t c:\temp\file123.gz
% for i=1:nfiles, gzip('-9',files{i}); end
%
% when nothing is passed out of this interface, the text output will be
% shown (disp-ed), but no return value will be available; this also
% applies to the command-style call. with one or more return values
% nothing will be printed to the MATLAB command window.
%
% no input arguments do a call to gzip's help page (gzip -h).

% Version:  v0.7f
% Build:    8110521
% Date:     Nov-05 2008, 9:00 PM CET
% Author:   Jochen Weber, SCAN Unit, Columbia University, NYC, NY, USA
% URL/Info: http://wiki.brainvoyager.com/BVQXtools

% default argument
callargs=' -h';

% argument given
if nargin > 0

    % argument is not char
    if ~ischar(varargin{1})

        % only valid if true output is requested and UINT8 input
        if nargout < 1 || ...
            nargin < 2 || ...
           ~isa(varargin{1}, 'uint8')
            error( ...
                'BVQXtools:BadArgument', ...
                'Only uint8 content can be handled via this syntax.' ...
            );
        end

        % also check option argument
        if ~ischar(varargin{2}) || ...
            numel(varargin{2}) ~= 2 || ...
            varargin{2}(1) ~= '-' || ...
           ~any('d123456789' == lower(varargin{2}(2)))
            error( ...
                'BVQXtools:BadArgument', ...
                'Illegal gzip mode for stream (de)compression.' ...
            );
        end

        % write content to file
        tn = tempname;

        % with correct extension (-1...9 / -d)
        if numel(varargin{2}) == 2 && ...
            all(lower(varargin{2}) == '-d')
            itn = [tn '.gz'];
            otn = tn;
        else
            itn = tn;
            otn = [tn '.gz'];
        end

        % try opening/writing file
        gfp = fopen(itn, 'w');
        if gfp < 1
            error( ...
                'BVQXtools:FileNotWritable', ...
                'Couldn''t write temporary file (%s).', ...
                itn ...
            );
        end
        fwrite(gfp, varargin{1}, 'uint8');
        fclose(gfp);

        % recall gzip with filename and option
        [s, w] = gzip(varargin{2}, itn);

        % check status
        if s ~= 0

            % delete file on failure
            try
                delete(itn);
            catch
                % nothing
            end

            % bail out now
            error( ...
                'BVQXtools:ErrorCallingExecutable', ...
                'Error processing stream (de)compression: %s.', ...
                w ...
            );
        end

        % no failure -> open result file
        gfp = fopen(otn, 'r');

        % on error
        if gfp < 1

            % delete both files and bail out
            try
                delete(otn);
            catch
                %nothing
            end
            try
                delete(itn);
            catch
                %nothing
            end
            error( ...
                'BVQXtools:FileNotReadable', ...
                'Couldn''t read gzip output file (%s).', ...
                otn ...
            );
        end

        % read, close, and delete file
        varargout{1} = fread(gfp, Inf, '*uint8');
        fclose(gfp);
        try
            delete(otn);
        catch
            %nothing
        end
        return;
    end

    % first argument must then be char
    callargs = ' ';

    % parse arguments into chair
    for c = 1:nargin

        % only allow char arguments though
        if ~ischar(varargin{c})
            error( ...
                'BVQXtools:BadArgument', ...
                'Non-character argument found.' ...
            );
        end

        % put into chain
        callargs = [callargs varargin{c} ' '];
    end
end

% call internal function
[s, r] = gzip_doit(callargs);

% no output requested
if nargout == 0

    % show any error
    if ~isempty(r)
        disp(r);
    end

% otherwise
else

    % first argument is result
    varargout{1} = s;

    % second is error message
    if nargout > 1
        varargout{2} = r;
    end
end


% real system call


function [status, result] = gzip_doit(arguments)

    % persistent location of binary
    persistent gzip_binlocation;

    % fill only once
    if ~ischar(gzip_binlocation)

        % for PCs
        if ispc

            % build location
            gzip_binlocation = ['"' bvqxtools_path('bin') '\gzip.exe"'];

        % for linux and others assume system path
        else
            gzip_binlocation = 'gzip';
        end
    end

    [status, result] = system([gzip_binlocation ' ' arguments]);
% end of function gzip_doit
